#pragma once

#include <boost/numeric/ublas/vector.hpp>

class SimResult {

public:
	typedef boost::numeric::ublas::vector<double> vec;

	static const int MAX_SIGNALS = 32;

	struct Data {
		int step;
		double time;
		double carDirection;
		vec carPos;
		double signals[MAX_SIGNALS];	// array of signals. Positions in the array correspond
										// to indices in the SignalProps array
	};

public:
	SimResult() : mData(0), mSize(0), mIndex(0), mNumSignals(0) { }

	~SimResult() {
		Clear();
	}

	void Clear() {
		if(mData != 0) {
			delete[] mData;
		}
		mData = 0;
		mSize = 0;
		mIndex = 0;
	}

	void Resize(int size) {
		Clear();
		mData = new Data[size];
		mSize = size;
		mIndex = 0;

		//memset(mData, 0, size * sizeof(*mData));
	}

	void Reset() {
		mIndex = 0;
	}

	bool Next() {
		mIndex++;
		// wrap around to 0
		if(mIndex >= mSize) {
			mIndex = 0;
			return false;
		}
		return true;
	}

	void Seek(int index) {
		if(index < 0 || index >= mSize) {
			std::ostringstream msg;
			msg << "Index out of bounds: " << index;
			throw std::runtime_error(msg.str());
		}
		mIndex = index;
	}

	Data &Current() {
		return mData[mIndex];
	}

	// return a pointer to the raw data
	Data *GetData() {
		return mData;
	}

	int GetIndex() const {
		return mIndex;
	}

	int GetSize() const {
		return mSize;
	}

	void AddSignal(const std::string &name) {
		if(mNumSignals >= MAX_SIGNALS) {
			std::ostringstream msg;
			msg << "Exceeded maximum number of signals: " << MAX_SIGNALS;
			throw std::runtime_error(msg.str());
		}
		mSignals[name] = mNumSignals++;
	}

	void SaveSignal(const std::string &name, double val) {
		Current().signals[mSignals[name]] = val;
	}

	int GetSignalIndex(const std::string &name) {
		return mSignals[name];
	}

private:
	Data *mData;
	int mSize;
	int mIndex;
	int mNumSignals;
	std::map<std::string, int> mSignals;		// map of signal names to indices
};
